Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\include\herald\sensor_delegate.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2020-2021 Herald Project Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#ifndef HERALD_SENSOR_DELEGATE_H
6
#define HERALD_SENSOR_DELEGATE_H
7
8
#include "datatype/sensor_type.h"
9
#include "datatype/proximity.h"
10
#include "datatype/payload_data.h"
11
#include "datatype/target_identifier.h"
12
#include "datatype/immediate_send_data.h"
13
#include "datatype/location.h"
14
#include "datatype/sensor_state.h"
15
16
#include <variant>
17
#include <array>
18
19
namespace herald {
20
  
21
using namespace datatype;
22
23
// /// \brief Base interface for classes wishing to implement callbacks for core low-level Herald proximity and presence events.
24
// class SensorDelegate {
25
// public:
26
//   SensorDelegate() = default;
27
//   virtual ~SensorDelegate() = default;
28
29
  
30
//   /// Detection of a target with an ephemeral identifier, e.g. BLE central detecting a BLE peripheral.
31
//   virtual void sensor(SensorType sensor, const TargetIdentifier& didDetect) = 0;
32
33
//   /// Read payload data from target, e.g. encrypted device identifier from BLE peripheral after successful connection.
34
//   virtual void sensor(SensorType sensor, const PayloadData& didRead, const TargetIdentifier& fromTarget) = 0;
35
36
//   /// Receive written immediate send data from target, e.g. important timing signal.
37
//   virtual void sensor(SensorType sensor, const ImmediateSendData& didReceive, const TargetIdentifier& fromTarget) = 0;
38
39
//   /// Read payload data of other targets recently acquired by a target, e.g. Android peripheral sharing payload data acquired from nearby iOS peripherals.
40
//   virtual void sensor(SensorType sensor, const std::vector<PayloadData>& didShare, const TargetIdentifier& fromTarget) = 0;
41
42
//   /// Measure proximity to target, e.g. a sample of RSSI values from BLE peripheral.
43
//   virtual void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget) = 0;
44
45
//   /// Detection of time spent at location, e.g. at specific restaurant between 02/06/2020 19:00 and 02/06/2020 21:00
46
//   template <typename LocationT>
47
//   void sensor(SensorType sensor, const Location<LocationT>& didVisit) {}
48
49
//   /// Measure proximity to target with payload data. Combines didMeasure and didRead into a single convenient delegate method
50
//   virtual void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget, const PayloadData& withPayload) = 0;
51
52
//   /// Sensor state update
53
//   virtual void sensor(SensorType sensor, const SensorState& didUpdateState) = 0;
54
// };
55
56
// TODO move this into a general header
57
template<typename F, typename... Args, typename = decltype(std::declval<F>()(std::declval<Args&&>()...))>
58
std::true_type isValidImpl(void*);
59
60
template<typename F, typename... Args>
61
std::false_type isValidImpl(...);
62
63
0
inline constexpr auto isValid = [] (auto f) {
64
0
  return [](auto&&... args) {
65
0
    return decltype(isValidImpl<decltype(f),decltype(args)&&...>(nullptr)){};
66
0
  };
67
0
};
Unexecuted instantiation: memoryarena-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: datatypes-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: base64string-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: datetime-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: randomuuid-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: uint8-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: uint16-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: uint32-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: uint64-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: sha256-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: distribution-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: sensorlogger-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: errorcontactlog-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: data-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: datatypesdataderived-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: blemacaddress-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: targetidentifier-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: test-util.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: crossplatform-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: beaconpayload-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: extendeddata-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: fixedpayload-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: bledevice-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: sample-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: ranges-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: analysisrunner-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: analysissensor-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: gaussian-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: advertparser-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: bledatabase-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: blecoordinator-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
Unexecuted instantiation: coordinator-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z
68
69
template<typename T>
70
struct TypeT {
71
  using Type = T;
72
};
73
74
template<typename T>
75
constexpr auto type = TypeT<T>{};
76
77
template<typename T>
78
T valueT(TypeT<T>);
79
80
81
constexpr auto hasSensorFunction = isValid(
82
  [](auto&& s,auto&& sensor,auto&& didRead,auto&& fromTarget) ->
83
    decltype(((decltype(s))s).get().sensor(sensor,didRead,fromTarget)) {}
84
);
85
// template<typename T,typename SE, typename DR, typename FT>
86
// using HasSensorFunctionT = decltype(hasSensorFunction(std::declval<T>(),std::declval<SE>(),std::declval<DR>(),std::declval<FT>()));
87
template<typename T,typename... Args>
88
using HasSensorFunctionT = decltype(hasSensorFunction(std::declval<T>(),std::declval<Args>()...));
89
template<typename T,typename... Args>
90
constexpr auto HasSensorFunctionV = HasSensorFunctionT<T,Args...>::value;
91
92
/// \brief A set of variant typed Sensor Delegate instances. Delegate callbacks can be invoked on the whole set, if supported by each.
93
template <typename... SensorDelegateTs>
94
class SensorDelegateSet {
95
public:
96
  static constexpr std::size_t Size = sizeof...(SensorDelegateTs);
97
98
  SensorDelegateSet(SensorDelegateTs&... dels) : 
99
    //delegates({std::variant<std::reference_wrapper<SensorDelegateTs&...>>(std::reference_wrapper<SensorDelegateTs&...>(dels...))}) {
100
    // delegates(std::experimental::make_array({std::reference_wrapper<SensorDelegateTs&...>(dels...)})) {
101
    delegates(std::array<
102
      std::variant<std::reference_wrapper<SensorDelegateTs>...>
103
      ,Size
104
    >({std::variant<std::reference_wrapper<SensorDelegateTs>...>(dels)...})) {
105
    // addDelegates(0,dels...);
106
  }
107
108
  // auto begin() -> decltype(std::declval<std::array<
109
  //     std::variant<std::reference_wrapper<SensorDelegateTs>...>
110
  //     ,Size
111
  //   >>().begin()) {
112
  //   return delegates.begin();
113
  // }
114
115
  // auto end() -> decltype(std::declval<std::array<
116
  //     std::variant<std::reference_wrapper<SensorDelegateTs>...>
117
  //     ,Size
118
  //   >>().end()) {
119
  //   return delegates.end();
120
  // }
121
122
  /// \brief Detection of a target with an ephemeral identifier, e.g. BLE central detecting a BLE peripheral.
123
  void sensor(SensorType sensor, const TargetIdentifier& didDetect) {
124
        for (auto& delegateV : delegates) {
125
      std::visit([sensor,didDetect](auto&& arg) {
126
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
127
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didDetect)>) {
128
          ((decltype(arg))arg).get().sensor(sensor,didDetect); // cast to call derived class function
129
        }
130
      }, delegateV);
131
    }
132
  }
133
134
  /// \brief Read payload data from target, e.g. encrypted device identifier from BLE peripheral after successful connection.
135
  void sensor(SensorType sensor, const PayloadData& didRead, const TargetIdentifier& fromTarget) {
136
    for (auto& delegateV : delegates) {
137
      std::visit([sensor,didRead,fromTarget](auto&& arg) {
138
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
139
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didRead),decltype(fromTarget)>) {
140
          ((decltype(arg))arg).get().sensor(sensor,didRead,fromTarget); // cast to call derived class function
141
        }
142
      }, delegateV);
143
    }
144
  }
145
146
  /// \brief Receive written immediate send data from target, e.g. important timing signal.
147
  void sensor(SensorType sensor, const ImmediateSendData& didReceive, const TargetIdentifier& fromTarget) {
148
    for (auto& delegateV : delegates) {
149
      std::visit([sensor,didReceive,fromTarget](auto&& arg) {
150
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
151
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didReceive),decltype(fromTarget)>) {
152
          ((decltype(arg))arg).get().sensor(sensor,didReceive,fromTarget); // cast to call derived class function
153
        }
154
      }, delegateV);
155
    }
156
  }
157
158
  /// \brief Read payload data of other targets recently acquired by a target, e.g. Android peripheral sharing payload data acquired from nearby iOS peripherals.
159
  void sensor(SensorType sensor, const DataSections<8>& didShare, const TargetIdentifier& fromTarget) {
160
    for (auto& delegateV : delegates) {
161
      std::visit([sensor,didShare,fromTarget](auto&& arg) {
162
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
163
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didShare),decltype(fromTarget)>) {
164
          ((decltype(arg))arg).get().sensor(sensor,didShare,fromTarget); // cast to call derived class function
165
        }
166
      }, delegateV);
167
    }
168
  }
169
170
  /// \brief Measure proximity to target, e.g. a sample of RSSI values from BLE peripheral.
171
  void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget) {
172
    for (auto& delegateV : delegates) {
173
      std::visit([sensor,didMeasure,fromTarget](auto&& arg) {
174
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
175
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didMeasure),decltype(fromTarget)>) {
176
          ((decltype(arg))arg).get().sensor(sensor,didMeasure,fromTarget); // cast to call derived class function
177
        }
178
      }, delegateV);
179
    }
180
  }
181
182
  /// \brief Detection of time spent at location, e.g. at specific restaurant between 02/06/2020 19:00 and 02/06/2020 21:00
183
  template <typename LocationT>
184
  void sensor(SensorType sensor, const Location<LocationT>& didVisit) {
185
    for (auto& delegateV : delegates) {
186
      std::visit([sensor,didVisit](auto&& arg) {
187
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
188
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didVisit)>) {
189
          ((decltype(arg))arg).get().sensor(sensor,didVisit); // cast to call derived class function
190
        }
191
      }, delegateV);
192
    }
193
  }
194
195
  /// \brief Measure proximity to target with payload data. Combines didMeasure and didRead into a single convenient delegate method
196
  void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget, const PayloadData& withPayload) {
197
    for (auto& delegateV : delegates) {
198
      std::visit([sensor,didMeasure,fromTarget,withPayload](auto&& arg) {
199
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
200
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didMeasure),decltype(fromTarget),decltype(withPayload)>) {
201
          ((decltype(arg))arg).get().sensor(sensor,didMeasure,fromTarget,withPayload); // cast to call derived class function
202
        }
203
      }, delegateV);
204
    }
205
  }
206
207
  /// \brief Sensor state update
208
  void sensor(SensorType sensor, const SensorState& didUpdateState) {
209
    for (auto& delegateV : delegates) {
210
      std::visit([sensor,didUpdateState](auto&& arg) {
211
        // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS
212
        if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didUpdateState)>) {
213
          ((decltype(arg))arg).get().sensor(sensor,didUpdateState); // cast to call derived class function
214
        }
215
      }, delegateV);
216
    }
217
  }
218
219
private:
220
  std::array<
221
    std::variant<std::reference_wrapper<SensorDelegateTs>...>
222
    ,
223
    Size
224
  > delegates;
225
226
  // template <typename LastT>
227
  // constexpr void addDelegates(int nextPos,LastT& last) {
228
  //   delegates[nextPos] = std::reference_wrapper<LastT>(last);
229
  // }
230
231
  // template <typename FirstT, typename SecondT, typename... RestT>
232
  // constexpr void addDelegates(int nextPos,FirstT& first, SecondT& second, RestT&... rest) {
233
  //   delegates[nextPos] = std::reference_wrapper<FirstT>(first);
234
  //   ++nextPos;
235
  //   addDelegates(nextPos,second,rest...);
236
  // }
237
};
238
239
240
} // end namespace
241
242
#endif